﻿using System.Collections.Generic;
using DC2010.Objects.Base;
using DC2010.Objects.Data;
using System;

namespace DC2010.Objects
{
    public class Inventory : BaseObject, ICloneable
    {
        public List<string> Items { get; set; }

        public event ItemDelegate OnItemRemoved;
        public event ItemDelegate OnItemAdded;

        public bool HasFreeSpot
        {
            get
            {
                for (int i = 0; i <= Items.Count; i++)
                {
                    if (Items.Count > i)
                    {
                        if (Items[i] == null) return true;
                    }
                }

                return Items.Count < MaxCapacity;
            }
        }

        public int MaxCapacity { get; set; }


        public Inventory()
        {
            MaxCapacity = 30;
            Items = new List<string>();
            GetLastAttackingWeaponPosition = CarryLocations.RightHand;
        }

        public int GetFirstFreeSpot()
        {
            //go through whole inventory. If u will find null in that place it is a free spot.
            for (int i = 0; i <= MaxCapacity; i++)
            {
                if (i <= Items.Count-1)
                {
                    if (Items[i] == null) return i;
                }
                else
                {
                    return Items.Count;
                }
            }

            return -1;
        }

        public int GetFirstFreeContainer()
        {
            //go through whole inventory. If u will find null in that place it is a free spot.
            for (int i = 0; i <= MaxCapacity-1; i++)
            {
                if (Items.Count > i)
                {
                    if (Items[i] != null)
                    {
                        ItemData itm = Root.I.ItemSystem.GetData(Items[i]);
                        ItemInfo iteminfo = Root.I.ItemSystem.GetInfo(itm.InfoId);

                        if ((iteminfo != null) && (iteminfo.IsContainerItem) && (iteminfo.ContainerType == ItemType.None))
                        {
                            if (itm.ContainerItems.HasFreeSpot)
                                return i;
                            //this is our container, return position of this container
                        }
                    }
                }
            }

            return -1;
        }

        public int GetFirstFreeContainer(ItemType it)
        {
            //go through whole inventory. If u will find null in that place it is a free spot.
            for (int i = 0; i <= MaxCapacity; i++)
            {
                if (Items.Count > i)
                {
                    if (Items[i] != null)
                    {
                        ItemData itm = Root.I.ItemSystem.GetData(Items[i]);
                        ItemInfo iteminfo = Root.I.ItemSystem.GetInfo(itm.InfoId);

                        //if ((iteminfo.IsContainerItem) && (iteminfo.ContainerType == it))
                        //{
                        //    if (itm.ContainerItems.HasFreeSpot)
                        //        return i;
                        //    //this is our container, return position of this container
                        //}
                    }
                }
                
            }

            return -1;
        }

        public string RemoveItemFromLastPosition()
        {
            string itemId = TakeItemFromPosition(Count-1);
            Items.RemoveAt(Count - 1);
            //Items[Count-1] = null;
            return itemId;
        }

        public string TakeItemFromPosition(CarryLocations es)
        {
            return TakeItemFromPosition((int)es);
        }

        private string TakeItemFromPosition(int position)
        {
            string s = GetItemAtPosition(position);

            if (s != null)
            {
                if (OnItemRemoved != null) OnItemRemoved(s);
            }

            return s;
        }

        /// <summary>
        /// Get the item at specified position but do not take of the item from inventory.
        /// </summary>
        /// <param name="es"></param>
        /// <returns></returns>
        public string GetItemAtPosition(CarryLocations es)
        {
            return GetItemAtPosition((int)es);
        }

        /// <summary>
        /// Get the item at specified position but do not take of the item from inventory.
        /// </summary>
        /// <param name="position"></param>
        /// <returns></returns>
        private string GetItemAtPosition(int position)
        {
            if (position < Items.Count)
            {
                return Items[position];
            }

            return null;
        }

        /// <summary>
        /// Number of carried items. TODO tahle kontrola nenni dobre, mohou tam byt i polozky s "";
        /// </summary>
        public int Count
        {
            get
            {
                return Items.Count;
            }
        }

        /// <summary>
        /// Inserts item to requested position
        /// </summary>
        /// <param name="es"></param>
        /// <param name="s"></param>
        /// <returns></returns>
        public bool PutItemToPosition(CarryLocations es, string s)
        {
            return PutItemToPosition((int)es, s);
        }

        private bool PutItemToPosition(int positionId, string s)
        {
            if (positionId < Items.Count)
            {
                Items[positionId] = s;
            }
            else
            {
                int l = positionId - Items.Count;

                for (int i = 0; i <= l; i++)
                {
                    Items.Add(null);
                }

                Items[positionId] = s;

                //fire event
                if (OnItemAdded != null) OnItemAdded(s);

                
            }
            return true;
        }

        public double CalculateWeight()
        {
            double sumWeight = 0;
            foreach (string s in Items)
            {
                ItemData id = Root.I.ItemSystem.GetData(s);
                ItemInfo info = Root.I.ItemSystem.GetInfo(id.InfoId);


                if (info.IsContainerItem) // sum weight for items in container
                {
                    foreach (string sss in id.ContainerItems.Items)
                    {
                        ItemData ii = Root.I.ItemSystem.GetData(sss);
                        ItemInfo infoC = Root.I.ItemSystem.GetInfo(ii.InfoId);

                        sumWeight += infoC.Weight;
                    }
                }
                else
                {
                    sumWeight += info.Weight;
                }
            }

            return sumWeight;
        }


        public List<string> GetCumulatedBuffs()
        {
            List<string> ls = new List<string>();
            //foreach (string s in Items)
            //{
            //    ItemData i = Root.I.ItemSystem.GetData(s);
            //    ls.AddRange(i.GetCumulatedBuffs());
            //}

            return ls;
        }

        public bool IsItemInInventory(string item)
        {
            foreach (string s in Items)
            {
                if (s == item) return true;
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iContainerId">Position in inventory</param>
        /// <param name="id">Item id to be put into container</param>
        public bool PutItemDirectlyIntoContainerItem(int iContainerId, string id)
        {
            //get container
            string sContainerItem = Items[iContainerId];
            ItemData pItm = Root.I.ItemSystem.GetData(sContainerItem);

            if (pItm != null)
            {
                if (pItm.ContainerItems.HasFreeSpot)
                {
                    pItm.ContainerItems.PutItemToFirstFreePosition(id);
                    return true;
                }
            }

            //we were not able to put item here
            return false;
        }

        public bool PutItemToFirstFreePosition(string id)
        {
            int iFirstFreeSpot = GetFirstFreeSpot();
            return PutItemToPosition(iFirstFreeSpot, id);
        }

        public object Clone()
        {
            Inventory i = new Inventory();
            i = (Inventory)i.MemberwiseClone();

            //create instances!
            foreach (string item in Items)
            {
                ItemInfo ii = Root.I.ItemSystem.GetInfo(item);

                if (ii==null)
                    i.Items.Add("");
                else
                {
                    i.Items.Add(ii.CreateData().Id);
                }
            }

            //i.Items = new List<string>(Items);

            return i;
        }

        public ItemData GetItemByInfoId(string infoId, bool remove)
        {
            foreach (string item in Items)
            {
                if (!string.IsNullOrEmpty(item))
                {
                    ItemData id = Root.I.ItemSystem.GetData(item);
                    ItemInfo ii = Root.I.ItemSystem.GetInfo(id.InfoId);

                    if (ii.Id == infoId)
                    {
                        //we have candidate!!!

                        if (remove)
                            //remove from inventory
                            Items.Remove(item);

                        return id;
                    }
                }
            }

            return null;

        }

        public ItemData Remove(ItemData itm)
        {
            if (Items.Contains(itm.Id))
                Items.Remove(itm.Id);

            return itm;
        }

        public ItemData GetAmmo()
        {
            //Items
            //Belt
            //Quiver

            //try ammo in left hand
            foreach (string item in Items)
            {
                ItemData id = Root.I.ItemSystem.GetData(item);
                ItemInfo ii = Root.I.ItemSystem.GetInfo(id.InfoId);

                if (ii.ItemType == ItemType.Ammo)
                {
                    //remove from inventory
                    Items.Remove(item);

                    return id;
                }
            }

            return null;
        }


        private CarryLocations GetLastAttackingWeaponPosition { get; set; }
        public ItemData GetAttackingWeapon()
        {
            //neni zatim vyreseno jak se naplni GetLastAttackingWeaponPosition
            return null;// GetItemAtPosition(GetLastAttackingWeaponPosition);
            // get from Root.I.GameSystem
        }
    }
}
